package com.briup.aspect;

import com.alibaba.fastjson.JSON;
import com.briup.annotation.SystemLog;
import com.briup.mapper.LogMapper;
import com.briup.pojo.Log;
import com.briup.result.Result;
import com.briup.util.IpUtils;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import nl.bitwalker.useragentutils.OperatingSystem;
import nl.bitwalker.useragentutils.UserAgent;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;

/**
 * 日志切面类
 */
@Component
@Aspect
@Slf4j
public class LogAspect {
    @Autowired
    private LogMapper logMapper;
    //切入点(注解的方式更自定义化)
    @Pointcut("@annotation(com.briup.annotation.SystemLog)")
    public void pt() {

    }
    @Around("pt()")
    public Object insertLog(ProceedingJoinPoint joinPoint) throws Throwable {
        //记录起始时间
        long start = System.currentTimeMillis();
        Log logInsert = beforeHandler(joinPoint);
        //执行核心方法
        Object proceed = joinPoint.proceed();
        afterHandler(logInsert, proceed, start);
        //返回结果
        return proceed;
    }

    /**
     * 处理程序之前
     *
     * @param joinPoint 加入点
     * @return {@link Log}
     */
    public Log beforeHandler(ProceedingJoinPoint joinPoint) {
        //创建Log对象
        Log logInsert = new Log();
        //获取请求对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //请求对象中Attribute中会存放用户名信息
        logInsert.setUsername(((String) request.getAttribute("username")));
        //获取注解中的business
        logInsert.setBusiness(((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(SystemLog.class).business());
        //获取请求路径
        logInsert.setRequestUrl(request.getRequestURL().toString());
        //获取请求方式
        logInsert.setRequestMethod(request.getMethod());
        // 获取浏览器信息
        String ieDetail = request.getHeader("User-Agent");
        // 将获取到的浏览器信息转换成UserAgent对象
        UserAgent userAgent = UserAgent.parseUserAgentString(ieDetail);
        // 获取系统信息
        OperatingSystem operatingSystem = userAgent.getOperatingSystem();
        //获取系统名称
        logInsert.setSystemName(operatingSystem.getName());
        //获取浏览器信息
        logInsert.setIeName(userAgent.getBrowser().getName());
        //获取真实IP
        logInsert.setIp(IpUtils.getIp(IpUtils.getIpAddr(request)).getIp());
        //获取ip来源(地址+运营商)
        logInsert.setIpSource(IpUtils.getIp(IpUtils.getIpAddr(request)).getAddr());
        //获取类地址
        logInsert.setClassPath(joinPoint.getSignature().getDeclaringTypeName());
        //获取方法名
        logInsert.setMethodName(joinPoint.getSignature().getName());
        //获取请求参数列表
        logInsert.setParamsJson(JSON.toJSONString(joinPoint.getArgs()));
        return logInsert;
    }
    /**
     * 处理程序后
     *
     * @param logInsert 日志插入
     * @param proceed   进行
     * @param start     开始
     */
    public void afterHandler(Log logInsert, Object proceed, Long start) {
        //获取响应状态码
        logInsert.setResponseCode(new Gson().fromJson(JSON.toJSONString(proceed), Result.class).getCode().toString());
        //获取响应信息
        logInsert.setResponseMsg(new Gson().fromJson(JSON.toJSONString(proceed), Result.class).getMessage());
        //记录结束时间
        long end = System.currentTimeMillis();
        //获取核心方法执行耗时
        logInsert.setSpendTime(end - start);
        //获取创建时间
        logInsert.setCreateTime(LocalDateTime.now());

        //插入数据库
        logMapper.insert(logInsert);
    }
}

